import json
import sqlalchemy
from flask import request, jsonify, Blueprint, g, Response
from project_model import Role, User, Permission
from tools import log_operations, build_permission_tree, token_required
from global_scope import get_db
from common_tools import DateTimeEncoder

role_bp = Blueprint("role_management", __name__, url_prefix='/role')
db = get_db()


@role_bp.route('/permissions/tree', methods=['GET'])
@log_operations
@token_required
def get_permissions_tree():
    """
    获取角色权限树。

    :return: 角色权限树的JSON响应
    """
    role = Role.query.filter(Role.id == g.current_role).first()
    if not role:
        return jsonify({'code': 1, 'message': 'Role not found'}), 404

    permissions = role.permissions
    if role.code == 'SUPER_ADMIN':
        permissions = Permission.query.all()

    menu_permissions_tree = build_permission_tree(permissions)

    response_data = {
        'code': 0,
        'message': 'OK',
        'data': menu_permissions_tree,
        'originUrl': '/role/permissions/tree'
    }
    response = Response(
        response=json.dumps(response_data, cls=DateTimeEncoder, ensure_ascii=False),
        status=200,
        mimetype='application/json'
    )
    return response


@role_bp.route('/page', methods=['GET'])
@log_operations
@token_required
def get_roles_list():
    """
    分页获取角色列表。

    :return: 角色列表的JSON响应
    """
    pageNo = request.args.get('pageNo', 1, type=int)
    pageSize = request.args.get('pageSize', 10, type=int)
    name = request.args.get('name', '')

    query = Role.query
    if name and isinstance(Role.name, sqlalchemy.Column):
        query = query.filter(Role.name.contains(name))

    total = query.count()
    roles = query.offset((pageNo - 1) * pageSize).limit(pageSize).all()

    roles_list = [
        {
            "id": role.id,
            "code": role.code,
            "name": role.name,
            "enable": bool(role.enable),
            "permissionIds": [permission.id for permission in role.permissions]
        }
        for role in roles
    ]

    response_data = {
        'code': 0,
        'message': 'OK',
        'data': {
            'pageData': roles_list,
            'total': total,
            'originUrl': f'/role/page?pageNo={pageNo}&pageSize={pageSize}&name={name}'
        }
    }
    return jsonify(response_data), 200


@role_bp.route('', methods=['GET'])
@log_operations
@token_required
def get_all_roles():
    """
    获取所有角色。

    :return: 所有角色的JSON响应
    """
    roles = Role.query.all()

    roles_list = [
        {
            "id": role.id,
            "code": role.code,
            "name": role.name,
            "enable": bool(role.enable)
        }
        for role in roles
    ]

    response_data = {
        'code': 0,
        'message': 'OK',
        'data': roles_list,
        'originUrl': '/role'
    }
    return jsonify(response_data), 200


@role_bp.route('/<int:role_id>', methods=['PATCH'])
@log_operations
@token_required
def update_role(role_id):
    """
    修改角色。

    :param role_id: 角色ID
    :return: 修改角色的JSON响应
    """
    data = request.get_json()
    role = db.session.get(Role, role_id)
    if not role:
        return jsonify({'code': 1, 'message': 'Role not found'}), 404

    role.code = data.get('code', role.code)
    role.name = data.get('name', role.name)
    role.enable = data.get('enable', role.enable)

    # 更新角色的权限
    if 'permissionIds' in data:
        permission_ids = data['permissionIds']
        role.permissions = Permission.query.filter(Permission.id.in_(permission_ids)).all()

    db.session.commit()

    response_data = {
        'code': 0,
        'message': 'Role updated successfully',
        'data': {
            'id': role.id,
            'code': role.code,
            'name': role.name,
            'enable': role.enable,
            'permissionIds': [permission.id for permission in role.permissions]
        },
        'originUrl': f'/role/{role_id}'
    }

    return jsonify(response_data), 200


@role_bp.route('/<int:role_id>', methods=['DELETE'])
@log_operations
@token_required
def delete_role(role_id):
    """
    删除角色。

    :param role_id: 角色ID
    :return: 删除角色的JSON响应
    """
    role = db.session.get(Role, role_id)
    if not role:
        return jsonify({'code': 1, 'message': 'Role not found'}), 404

    db.session.delete(role)
    db.session.commit()

    response_data = {
        'code': 0,
        'message': 'Role deleted successfully',
        'data': {},
        'originUrl': f'/role/{role_id}'
    }
    return jsonify(response_data), 200


@role_bp.route('/users/remove/<int:role_id>', methods=['PATCH'])
@log_operations
@token_required
def remove_role_from_users(role_id):
    """
    批量取消分配角色。

    :param role_id: 角色ID
    :return: 取消分配角色的JSON响应
    """
    role = db.session.get(Role, role_id)
    if not role:
        return jsonify({'code': 1, 'message': 'Role not found'}), 404

    data = request.get_json()
    user_ids = data.get('userIds', [])
    if not user_ids:
        return jsonify({'code': 1, 'message': 'No userIds provided'}), 400

    users = User.query.filter(User.id.in_(user_ids)).all()
    if not users:
        return jsonify({'code': 1, 'message': 'Users not found'}), 404

    for user in users:
        if role in user.roles:
            user.roles.remove(role)

    db.session.commit()

    response_data = {
        'code': 0,
        'message': 'Role removed from users successfully',
        'data': {},
        'originUrl': f'/role/users/remove/{role_id}'
    }
    return jsonify(response_data), 200


@role_bp.route('/users/add/<int:role_id>', methods=['PATCH'])
@log_operations
@token_required
def add_role_to_users(role_id):
    """
    批量分配角色。

    :param role_id: 角色ID
    :return: 分配角色的JSON响应
    """
    role = db.session.get(Role, role_id)
    if not role:
        return jsonify({'code': 1, 'message': 'Role not found'}), 404

    data = request.get_json()
    user_ids = data.get('userIds', [])
    if not user_ids:
        return jsonify({'code': 1, 'message': 'No userIds provided'}), 400

    users = User.query.filter(User.id.in_(user_ids)).all()
    if not users:
        return jsonify({'code': 1, 'message': 'Users not found'}), 404

    for user in users:
        if role not in user.roles:
            user.roles.append(role)

    db.session.commit()

    response_data = {
        'code': 0,
        'message': 'Role added to users successfully',
        'data': {},
        'originUrl': f'/role/users/add/{role_id}'
    }
    return jsonify(response_data), 200


@role_bp.route('', methods=['POST'])
@log_operations
@token_required
def add_role():
    """
    新增角色。

    :return: 新增角色的JSON响应
    """
    data = request.get_json()
    required_fields = ['code', 'name']

    for field in required_fields:
        if field not in data:
            return jsonify({'code': 1, 'message': f'Missing required field: {field}'}), 400

    new_role = Role(
        code=data['code'],
        name=data['name'],
        enable=data.get('enable', 1)
    )

    # 添加角色的权限
    if 'permissionIds' in data:
        permission_ids = data['permissionIds']
        new_role.permissions = Permission.query.filter(Permission.id.in_(permission_ids)).all()

    db.session.add(new_role)
    db.session.commit()

    response_data = {
        'code': 0,
        'message': 'Role added successfully',
        'data': {
            'id': new_role.id,
            'code': new_role.code,
            'name': new_role.name,
            'enable': new_role.enable,
            'permissionIds': [permission.id for permission in new_role.permissions]
        },
        'originUrl': '/role'
    }
    return jsonify(response_data), 201
